<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Advanced Three.js Scene</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: radial-gradient(circle, #000428, #004e92); /* 渐变背景 */
        }
        canvas {
            display: block;
        }
        .overlay {
            position: absolute;
            top: 10px;
            left: 10px;
            color: white;
            font-size: 1.2em;
            z-index: 1;
            text-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
        }
    </style>
</head>
<body>
    <div class="overlay">Advanced Three.js Scene</div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.159.0/three.min.js"></script>
    <script>
        let scene, camera, renderer, sphere, particles, light1, light2, rippleGroup, clock;
        
        function init() {
            clock = new THREE.Clock();

            // Scene and camera setup
            scene = new THREE.Scene();
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(0, 5, 20);

            // Renderer setup
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.shadowMap.enabled = true;  // 开启阴影
            document.body.appendChild(renderer.domElement);

            // Reflective dynamic sphere
            const sphereGeometry = new THREE.SphereGeometry(3, 64, 64);
            const sphereMaterial = new THREE.MeshPhysicalMaterial({
                color: 0x88ccff,
                metalness: 0.8,
                roughness: 0.3,
                emissive: 0x222222,
                clearcoat: 1,
                clearcoatRoughness: 0.1,
                reflectivity: 1
            });
            sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
            sphere.castShadow = true;
            sphere.position.set(0, 3, 0);
            scene.add(sphere);

            // Particle clouds
            particles = createParticleCloud(3000, 50);
            scene.add(particles);

            // Dynamic ripple rings
            rippleGroup = new THREE.Group();
            createRippleEffect(rippleGroup, 5);
            scene.add(rippleGroup);

            // Dynamic lights
            light1 = new THREE.PointLight(0xff0099, 2, 50);
            light1.position.set(10, 10, 10);
            light1.castShadow = true;
            scene.add(light1);

            light2 = new THREE.PointLight(0x00ffff, 2, 50);
            light2.position.set(-10, 10, -10);
            light2.castShadow = true;
            scene.add(light2);

            const ambientLight = new THREE.AmbientLight(0x202020, 1);
            scene.add(ambientLight);

            // Animate
            animate();
        }

        function createParticleCloud(count, size) {
            const geometry = new THREE.BufferGeometry();
            const positions = new Float32Array(count * 3);
            const colors = new Float32Array(count * 3);

            for (let i = 0; i < count; i++) {
                positions[i * 3] = (Math.random() - 0.5) * size;
                positions[i * 3 + 1] = (Math.random() - 0.5) * size;
                positions[i * 3 + 2] = (Math.random() - 0.5) * size;

                colors[i * 3] = Math.random();
                colors[i * 3 + 1] = Math.random();
                colors[i * 3 + 2] = Math.random();
            }

            geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
            geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));

            const material = new THREE.PointsMaterial({
                size: 0.2,
                vertexColors: true,
                transparent: true,
                opacity: 0.8,
                blending: THREE.AdditiveBlending
            });

            return new THREE.Points(geometry, material);
        }

        function createRippleEffect(group, count) {
            for (let i = 0; i < count; i++) {
                const ringGeometry = new THREE.RingGeometry(0.5, 5, 64);
                const ringMaterial = new THREE.MeshBasicMaterial({
                    color: new THREE.Color(`hsl(${(i * 360) / count}, 100%, 50%)`),
                    transparent: true,
                    opacity: 0.5,
                    side: THREE.DoubleSide
                });
                const ring = new THREE.Mesh(ringGeometry, ringMaterial);
                ring.rotation.x = Math.PI / 2;
                group.add(ring);
            }
        }

        function updateRippleEffect(group) {
            group.children.forEach((ring, index) => {
                ring.scale.setScalar(1 + Math.sin(clock.getElapsedTime() + index) * 0.5);
                ring.material.opacity = 0.5 + 0.5 * Math.sin(clock.getElapsedTime() + index);
            });
        }

        function animate() {
            requestAnimationFrame(animate);

            const elapsedTime = clock.getElapsedTime();

            // Update sphere rotation
            sphere.rotation.y += 0.01;
            sphere.material.color.setHSL(Math.sin(elapsedTime * 0.5), 0.5, 0.5);

            // Update particles
            particles.rotation.y += 0.002;

            // Update ripples
            updateRippleEffect(rippleGroup);

            // Update lights
            light1.position.x = Math.sin(elapsedTime) * 15;
            light1.position.z = Math.cos(elapsedTime) * 15;

            light2.position.x = Math.cos(elapsedTime) * 15;
            light2.position.z = Math.sin(elapsedTime) * 15;

            // Camera orbit
            camera.position.x = Math.sin(elapsedTime * 0.2) * 20;
            camera.position.z = Math.cos(elapsedTime * 0.2) * 20;
            camera.lookAt(0, 3, 0);

            // Render scene
            renderer.render(scene, camera);
        }

        // Handle window resize
        window.addEventListener('resize', () => {
            renderer.setSize(window.innerWidth, window.innerHeight);
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
        });

        // Initialize scene
        window.onload = init;
    </script>
</body>
</html>